home *** CD-ROM | disk | FTP | other *** search
- /* advscn.c - a lexical scanner for the adventure compiler */
- /*
- Copyright (c) 1986, by David Michael Betz
- All rights reserved
- */
-
- #include "advcom.h"
-
- /* useful definitions */
- #define maplower(ch) (isupper(ch) ? tolower(ch) : ch)
-
- /* global variables */
- int errcount=0; /* error count */
- int t_value; /* numeric value */
- char t_token[TKNSIZE+1];/* token string */
- char *t_names[] = {
- 0,
- "(",
- ")",
- "STRING",
- "IDENTIFIER",
- "NUMBER",
- "EOF"
- };
-
- /* external variables */
- extern FILE *ifp; /* input file pointer */
- extern int msgoff; /* message section offset */
-
- /* local variables */
- static int savetkn = 0; /* look ahead token */
- static int savech = 0; /* look ahead character */
- static char fname[200]; /* include file name */
- static char line[200]; /* current input line */
- static char *lptr; /* line pointer */
- static int lnum; /* line number */
- static int ieof; /* input end of file flag */
- static int save_lnum; /* saved lnum */
- static FILE *save_ifp; /* saved ifp */
- static int scnt; /* count of characters in string */
-
- /* sinit - initialize the scanner */
- sinit()
- {
- /* setup the line buffer */
- lptr = line; *lptr = 0;
- lnum = 0;
-
- /* no include file yet */
- save_ifp = NULL;
-
- /* no lookahead yet */
- savech = 0;
- savetkn = 0;
-
- /* not eof yet */
- ieof = FALSE;
- }
-
- /* token - get the next token */
- int token()
- {
- int tkn;
-
- if (tkn = savetkn)
- savetkn = 0;
- else
- tkn = rtoken();
- return (tkn);
- }
-
- /* stoken - save a token */
- stoken(tkn)
- int tkn;
- {
- savetkn = tkn;
- }
-
- /* rtoken - read the next token */
- int rtoken()
- {
- int ch;
-
- /* check the next character */
- for (;;)
- switch (ch = skipspaces()) {
- case EOF: return (T_EOF);
- case '(': strcpy(t_token,"("); return (T_OPEN);
- case ')': strcpy(t_token,")"); return (T_CLOSE);
- case '"': return (getstring());
- case ';': while (getch() != '\n'); break;
- default: return (getid(ch));
- }
- }
-
- /* getstring - get a string */
- int getstring()
- {
- int ch,sflag;
-
- t_value = msgoff;
- sflag = FALSE;
- scnt = 0;
- while ((ch = getch()) != EOF && ch != '"')
- if (isspace(ch))
- sflag = TRUE;
- else {
- if (ch == '\\')
- switch (ch = getch()) {
- case 'n': ch = '\n'; break;
- case 't': ch = '\t'; break;
- }
- if (sflag)
- { wputc(' '); sflag = FALSE; }
- wputc(ch);
- }
- if (sflag)
- wputc(' ');
- strdone();
- strcpy(t_token,"{string}");
- return (T_STRING);
- }
-
- /* getid - get an identifier */
- int getid(ch)
- int ch;
- {
- char *p;
-
- p = t_token; *p++ = maplower(ch);
- while ((ch = getch()) != EOF && isidchar(ch))
- *p++ = maplower(ch);
- *p = EOS;
- savech = ch;
- return (isnumber(t_token,&t_value) ? T_NUMBER : T_IDENTIFIER);
- }
-
- /* isnumber - check if this string is a number */
- int isnumber(str,pval)
- char *str; int *pval;
- {
- int digits;
- char *p;
-
- /* initialize */
- p = str; digits = 0;
-
- /* check for a sign */
- if (*p == '+' || *p == '-')
- p++;
-
- /* check for a string of digits */
- while (isdigit(*p))
- p++, digits++;
-
- /* make sure there was at least one digit and this is the end */
- if (digits == 0 || *p)
- return (FALSE);
-
- /* convert the string to an integer and return successfully */
- if (*str == '+') ++str;
- *pval = atoi(str);
- return (TRUE);
- }
-
- /* wputc - put a character into the output file */
- wputc(ch)
- int ch;
- {
- ad_putc(encode(ch));
- scnt++;
- }
-
- /* strdone - finish a string */
- strdone()
- {
- wputc('\0');
- while (scnt & 3)
- wputc('\0');
- msgoff += scnt >> 2;
- }
-
- /* skipspaces - skip leading spaces */
- skipspaces()
- {
- int ch;
-
- while ((ch = getch()) && isspace(ch))
- ;
- return (ch);
- }
-
- /* isidchar - is this an identifier character */
- int isidchar(ch)
- int ch;
- {
- return (!isspace(ch) && ch != '(' && ch != ')' && ch != '"');
- }
-
- /* getch - get the next character */
- int getch()
- {
- FILE *fp;
- int ch;
-
- /* check for a lookahead character */
- if (ch = savech)
- savech = 0;
-
- /* check for a buffered character */
- else if (ch = *lptr)
- lptr++;
-
- /* check for end of file */
- else if (ieof)
- ch = EOF;
-
- /* read another line */
- else {
-
- /* read the line */
- for (lptr = line; (ch = getchr()) != EOF && (*lptr++ = ch) != '\n'; )
- ;
- *lptr = 0;
- lnum++;
-
- /* check for an included file */
- if (line[0] == '@') {
-
- /* open the file */
- strcpy(fname,&line[1]); fname[strlen(fname)-1] = 0;
- if ((fp = fopen(fname,"r")) == NULL) {
- printf("Can't open include file: %s\n",fname);
- exit();
- }
- printf("[ including %s ]\n",fname);
-
- /* setup input from the file */
- save_lnum = lnum;
- save_ifp = ifp;
- ifp = fp;
-
- /* setup for the first line */
- lptr = line; *lptr = 0;
- lnum = 0;
- }
-
- /* otherwise this must be an input line */
- else {
-
- /* terminate the line with a newline */
- *lptr++ = '\n'; *lptr = 0;
-
- /* check for end of file */
- if (ch == EOF)
- ieof = TRUE;
-
- /* update the line number and setup for the new line */
- lptr = line;
- }
-
- /* get a character */
- ch = getch();
- }
-
- /* return the current character */
- return (ch);
- }
-
- /* getchr - get a character checking for end of file */
- int getchr()
- {
- int ch;
-
- if ((ch = getc(ifp)) == EOF || ch == '\032') {
- if (save_ifp) {
- printf("[ end of %s ]\n",fname);
- fclose(ifp);
- lnum = save_lnum;
- ifp = save_ifp;
- save_ifp = NULL;
- ch = getchr();
- }
- else
- ch = EOF;
- }
- else if (ch == '\r')
- ch = getchr();
- return (ch);
- }
-
- /* encode - encode a single character */
- int encode(ch)
- int ch;
- {
- return ((ch - 30) & 0xFF);
- }
-
- /* error - report an error in the current line */
- error(msg)
- char *msg;
- {
- char *p;
-
- printf(">>> %s <<<\n>>> in line %d <<<\n%s",msg,lnum,line);
- for (p = line; p < lptr; p++)
- if (*p == '\t')
- putchar('\t');
- else
- putchar(' ');
- printf("^\n");
- errcount++;
- #ifdef MAC
- macpause();
- #endif
- }
-
- /* xerror - report an error in the current line */
- xerror(msg)
- char *msg;
- {
- printf(">>> %s <<<\n",msg);
- errcount++;
- }